﻿
Imports System.Runtime.CompilerServices
Imports osi.root.formation
Imports osi.root.connector
Imports osi.root.constants

Public Module _pattern_matching
    <Extension()> Public Function match_pattern(ByVal str As String,
                                                ByVal patterns As vector(Of String),
                                                Optional ByVal care_case As Boolean = False) As Boolean
        Return fitfilterSet(patterns, str, care_case)
    End Function

    <Extension()> Public Function match_pattern(ByVal str As String,
                                                ByVal pattern As String,
                                                Optional ByVal care_case As Boolean = False) As Boolean
        Return fitfilter(pattern, str, care_case)
    End Function

    Public Function fitfilterSet(ByVal filterSet As vector(Of String),
                                 ByVal str As String,
                                 Optional ByVal careCase As Boolean = False) As Boolean
        Return stringfilter.fitfilterList(filterSet, str, careCase)
    End Function

    Public Function fitfilter(ByVal filter As String,
                              ByVal str As String,
                              Optional ByVal careCase As Boolean = False) As Boolean
        Dim rtn As Int32
        Dim extCode As Boolean = False
        rtn = stringfilter.fitfilter(filter, str, careCase)
        If rtn = stringfilter.fitUndertermind Then
            If strlen(filter) > 0 AndAlso filter(0) = stringfilter.cutSign Then
                extCode = True
            Else
                extCode = False
            End If
        Else
            extCode = (rtn = stringfilter.fitTrue)
        End If

        Return extCode
    End Function
End Module

Namespace stringfilter
    Public Module stringfilter
        Public Const fitTrue As Byte = 1
        Public Const fitFalse As Byte = 2
        Public Const fitUndertermind As Byte = 0
        Public Const cutSign As Char = character.minus_sign
        Public Const addSign As Char = character.plus_sign
        Public Const multiCharSign As Char = filesystem.multi_pattern_matching_character
        Public Const singleCharSign As Char = filesystem.single_pattern_matching_character

        Friend Function fitfilterList(ByVal filterSet As vector(Of String),
                                      ByVal name As String,
                                      Optional ByVal careCase As Boolean = False) As Boolean
            Dim i As Int32
            Dim result As Int32
            Dim fited As Boolean = False

            For i = 0 To filterSet.size() - 1
                result = fitfilter(filterSet(i), name, careCase)
                If result = fitFalse Then
                    fited = False
                ElseIf (result = fitTrue) Then
                    fited = True
                End If
            Next

            Return fited
        End Function

        Private Function fitfilterLite(ByVal definition As String,
                                       ByVal name As String,
                                       Optional ByVal careCase As Boolean = False) As Boolean
            Dim i As Int32 = 0
            Dim j As Int32 = 0
            Dim definitionLen As Int32 = strlen(definition)
            Dim nameLen As Int32 = strlen(name)
            Dim rtn As Boolean

            definition += character.null
            name += character.null
            While (i < definitionLen AndAlso j < nameLen)
                If definition(i) = multiCharSign Then
                    i += 1
                    While (definition(i) = multiCharSign)
                        i += 1
                    End While
                    rtn = False
                    While (j <= nameLen)
                        While j <= nameLen
                            If Not charsame(name(j), definition(i), careCase) Then
                                j += 1
                            Else
                                Exit While
                            End If
                        End While

                        rtn = fitfilterLite(strmid(definition, i, definitionLen - i),
                                            strmid(name, j, nameLen - j), careCase)
                        If rtn Then
                            Exit While
                        Else
                            j += 1
                        End If
                    End While

                    If rtn Then
                        i = definitionLen
                        j = nameLen
                    End If
                    Exit While
                ElseIf definition(i) = singleCharSign Then
                    i += 1
                    j += 1
                Else
                    If charsame(definition(i), name(j), careCase) Then
                        i += 1
                        j += 1
                    Else
                        Exit While
                    End If
                End If
            End While

            While definition(i) = multiCharSign
                i += 1
            End While
            If i < definitionLen OrElse j < nameLen Then
                Return False
            Else
                Return True
            End If
        End Function

        Friend Function fitfilter(ByVal definition As String,
                                  ByVal name As String,
                                  Optional ByVal careCase As Boolean = False) As Byte
            If strlen(definition) > 0 AndAlso definition(0) = cutSign Then
                If (fitfilterLite(strmid(definition, 1), name, careCase)) Then
                    Return fitFalse
                Else
                    Return fitUndertermind
                End If
            Else
                Dim offside As Byte = 0
                If strlen(definition) > 0 AndAlso definition(0) = addSign Then
                    offside = 1
                End If
                If (fitfilterLite(strmid(definition, offside), name, careCase)) Then
                    Return fitTrue
                Else
                    Return fitUndertermind
                End If
            End If
        End Function
    End Module
End Namespace
